/**
 * @description 手机端的可拖动排序的列表插件，不依赖第三方类库
 * @author yuezk001#gmail.com   2013-11-28
 * @version 1.0
 */
;(function (global, undefined) {
    var emptyFn = function () { };

    function DragView(id, option) {
        //强制使用`new`关键字
        if (!(this instanceof DragView)) {
            return new DragView(id, option);
        }

        this.id = id;
        this.items = [];
        this.option = option || {};
        //回调函数
        this.onBeforeStart = (typeof this.option.onBeforeStart == 'function') ? this.option.onBeforeStart : function () { return true; };
        this.onDragStart = (typeof this.option.onDragStart == 'function') ? this.option.onDragStart : emptyFn;
        this.onDrag = (typeof this.option.onDrag == 'function') ? this.option.onDrag : emptyFn;
        this.onDragEnd = (typeof this.option.onDragEnd == 'function') ? this.option.onDragEnd : emptyFn;

        this.init();
    }
    //定义状态量 
    DragView.STATE = {
        DRAG_START: 1,
        DRAGING: 2,
        DRAG_END: 3
    };

    DragView.prototype = {
        constructor: DragView,
        init: function () {
            this.host = document.getElementById(this.id);
            this.host.style.position = 'relative';

            for (var i = 0, children = this.host.childNodes, len = children.length; i < len; i++) {
                if (children[i].nodeType == 1) {
                    children[i].instance = this; //保存实例的引用，方便调用
                    this.items.push(children[i]);
                }
            }
            this.state = DragView.STATE.DRAG_END;
            this._buildUI();
            this._bindEvent();
        },
        getItems: function () {
            var items = [];

            for (var i = 0, children = this.host.childNodes, len = children.length; i < len; i++) {
                if (children[i].nodeType == 1) {
                    items.push(children[i]);
                }
            }

            return items;
        },
        _buildUI: function () {
            var me = this;
            //添加拖动端图标
            for (var i = 0, len = me.items.length; i < len; i++) {
                me.items[i].style.position = 'relative';
                var handle = document.createElement('div');
                handle.className = 'drag-view-handle';

                me._applyStyle(handle, {
                    position: 'absolute',
                    width: '45px',
                    height: me.items[i].clientHeight + 'px',
                    right: '0px',
                    top: '0px',
                    'background-color': 'black',
//                    background: 'url(./static/mobile/img/btn_gear.png) center center no-repeat',
                    zIndex: 100
                });

                me.items[i].appendChild(handle);
            }
        },
        /*绑定事件处理函数*/
        _bindEvent: function () {
            var me = this;

            for (var i = 0, len = this.items.length; i < len; i++) {
                (function (index) {
                    var item = me.items[index];
                    item.addEventListener('touchstart', me._onTouchStart, false);
                    item.addEventListener('touchmove', me._onTouchMove, false);
                    item.addEventListener('touchend', me._onTouchEnd, false);
                })(i);
            }
        },
        _onTouchStart: function (e) {
            if (e.target.className !== 'drag-view-handle') {
                return;
            }
            e.preventDefault(); //防止屏幕滚动

            var instance = this.instance,
                touches = e.touches;

            if (instance.onBeforeStart() !== true) {
                return;
            }

            if (instance.state != DragView.STATE.DRAG_END){
                return;
            }

            instance.currentItem = this; //当前选中的项
            instance.currentIndex = instance._getIndex(instance.currentItem);

            //复制一个元素用来拖动
            instance.holder = this.cloneNode(true);
            instance.holder.className = 'drag-view-holder';
            instance.host.appendChild(instance.holder);

            instance._initPosition();
            instance.touchPos = {
                pageX: touches[0].pageX,
                pageY: touches[0].pageY
            };

            //隐藏当前元素
            this.style.visibility = 'hidden';

            instance.state = DragView.STATE.DRAG_START;
            instance.onDragStart();
        },
        _onTouchMove: function (e) {
            var instance = this.instance,
                touches = e.touches;

            if (instance.state == DragView.STATE.DRAGING) {//如果正在移动，调整拖动的位置

                instance._changePosition(touches[0]);
                if (instance.moveDirection == 'top') { //向上移动
                    if (instance.currentIndex > 0) { //如果不是第一项
                        var item = instance.currentItem.previousElementSibling;
                        if (instance.holder.offsetTop > item.offsetTop &&
                            instance.holder.offsetTop < item.offsetTop + item.offsetHeight / 2) {
                            instance.host.insertBefore(instance.currentItem, item);
                            instance.currentIndex--;
                        }
                    }
                } else if (instance.moveDirection == 'bottom') {//向下移动
                    if (instance.currentIndex < instance.items.length - 1) { //如果不是最后一项
                        var item = instance.currentItem.nextElementSibling;
                        if (instance.holder.offsetTop + instance.holder.offsetHeight > item.offsetTop + item.offsetHeight / 2) {
                            instance._insertAfter(instance.currentItem, item);
                            instance.currentIndex++;
                        }
                    }
                }

                instance.touchPos = {
                    pageX: touches[0].pageX,
                    pageY: touches[0].pageY
                };
                instance.onDrag();
            } else if (instance.state == DragView.STATE.DRAG_START) {
                instance.state = DragView.STATE.DRAGING;
            }
        },
        _onTouchEnd: function (e) {

            var instance = this.instance;

            if (e.touches.length > 0) { //说明有手指在屏幕上
                return;
            }

            if (instance.state != DragView.STATE.DRAG_END) {

                instance.currentItem.style.visibility = '';
                instance.holder.style.dispaly = 'none';
                instance.host.removeChild(instance.holder);
                delete instance.holder;

                instance.state = DragView.STATE.DRAG_END;
                instance.onDragEnd();
            }

        },
        _applyStyle: function (el, style) {
            for (var prop in style) {
                el.style[prop] = style[prop];
            }
        },
        _initPosition: function () {
            //初始化移动时占位元素的位置
            var computedStyle = global.getComputedStyle(this.currentItem);

            this._applyStyle(this.holder, {
                position: 'absolute',
                left: this.currentItem.offsetLeft + 'px',
                top: this.currentItem.offsetTop + 'px',

                width: parseInt(computedStyle.width) + 'px',
                height: parseInt(computedStyle.height) + 'px',

                paddingTop: parseInt(computedStyle.paddingTop, 10) + 'px',
                paddingRight: parseInt(computedStyle.paddingRight, 10) + 'px',
                paddingBottom: parseInt(computedStyle.paddingBottom, 10) + 'px',
                paddingLeft: parseInt(computedStyle.paddingLeft, 10) + 'px',

                borderTop: computedStyle.borderTop,
                borderRight: computedStyle.borderRight,
                borderBottom: computedStyle.borderBottom,
                borderLeft: computedStyle.borderLeft,

                boxShadow: '0 0 3px rgba(0, 0, 0, .5)',
                background: computedStyle.background
            });
        },
        _changePosition: function (touch) {
            var topChange = touch.pageY - this.touchPos.pageY;
            //移动的方向
            this.moveDirection = topChange > 0 ? 'bottom' : 'top';
            var top = parseInt(this.holder.style.top, 10) + topChange;
            //限定在list高度之内移动
            top = Math.max(0, Math.min(top, this.host.offsetHeight - this.holder.offsetHeight));

            this.holder.style.top = top + 'px';
        },
        _insertAfter: function (newItem, refItem) {
            var parent = refItem.parentNode;
            if (parent.lastChild == refItem) {
                parent.appendChild(newItem);
            } else {
                parent.insertBefore(newItem, refItem.nextSibling);
            }
        },
        _getIndex: function (item) {
            var index = -1, j = 0;
            for (var i = 0, children = this.host.childNodes, len = children.length; i < len; i++) {
                if (children[i].nodeType == 1) {
                    if (item === children[i]) {
                        index = j;
                        break;
                    }
                    j++;
                }
            }
            return index;
        }
    };

    global.DragView = DragView;
})(window);
